#include "app_buffer.h"
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "log.h"

app_buffer_t *app_buffer_init(void)
{
    /* 创建 主缓冲区结构体 */
    app_buffer_t *buffer = (app_buffer_t *)malloc(sizeof(app_buffer_t));
    if (buffer == NULL)
    {
        log_fatal("app_buffer_init malloc error");
        return NULL;
    }

    /* 创建 子缓冲区结构体 */
    for (size_t i = 0; i < 2; i++)
    {
        app_buffer_sub_t *sub_buffer = (app_buffer_sub_t *)malloc(sizeof(app_buffer_sub_t));
        sub_buffer->data_len = 0;
        sub_buffer->data_ptr = malloc(APP_BUFFER_SIZE);
        sub_buffer->total_len = APP_BUFFER_SIZE;
        buffer->sub_buffers[i] = sub_buffer;
    }
    
    buffer->read_index = 0; /* 0号缓冲区负责读 默认 */
    buffer->write_index = 1; /* 1号缓冲区负责写 默认 */
    /* 初始化锁 */
    pthread_mutex_init(&buffer->read_lock, NULL);
    pthread_mutex_init(&buffer->swap_lock, NULL);

    return buffer;
}

static void app_buffer_swap(app_buffer_t *buffer)
{
    log_info("app_buffer_swap");
    pthread_mutex_lock(&buffer->swap_lock);
    buffer->read_index = buffer->read_index == 0 ? 1 : 0;
    buffer->write_index = buffer->write_index == 0 ? 1 : 0;
    pthread_mutex_unlock(&buffer->swap_lock);
}

int app_buffer_write(app_buffer_t *buffer, char *write_data, int write_data_len)
{
    /* 1 检查 不能超过总空间 且 不能超过127 （一个字节的帧长度） */
    if (write_data_len > APP_BUFFER_SIZE || write_data_len > 127)
    {
        log_error("超过总空间或帧长度超过127");
        return -1;
    }
    /* 2 获取写锁 */
    pthread_mutex_lock(&buffer->swap_lock);

    /* 读取写缓冲区 */
    app_buffer_sub_t *write_sub_buffer = buffer->sub_buffers[buffer->write_index];

    /* 检查 写缓冲区是否够用 */
    int remain_len = write_sub_buffer->total_len - write_sub_buffer->data_len;
    if (remain_len < write_data_len + 1) /* 加帧头 */
    {
        log_error("写缓冲区不够用");
        return -1;
    }
    
    /* 3 写入数据 */
    /* 写入帧头 数据长度 */
    write_sub_buffer->data_ptr[write_sub_buffer->data_len] = write_data_len;

    /* 写入数据 */
    memcpy(write_sub_buffer->data_ptr + write_sub_buffer->data_len + 1, write_data, write_data_len);

    /* 更新数据长度 */
    write_sub_buffer->data_len += write_data_len + 1;
    pthread_mutex_unlock(&buffer->swap_lock);
    return 0;
}

/**
 * @brief : 从缓冲区读取数据
 * @param    buffer: 的结构体指针
 * @param    read_data: 读取的数据
 * @param    read_data_len: 读取的数据长度
 * @return int 读取成功 返回实际读取的数据长度 读取失败 返回-1
 * 
 * 步骤 
 * 1 获取读锁
 * 2 判断 读缓冲区是否为空
 * 3 如果数据为空
 *      3.1 进行读写切换
 *      3.2 重新根据读写下标获取读缓冲区
 *      3.3 判断 读缓冲区是否为空
 * 4 如果有数据 取出 帧头数据长度
 * 5 如果帧头数据长度 大于 读缓冲区数据长度
 *      5.1 把数据读取到 read_buff中
 *      5.2 删除已读取的数据
 *      5.3 更新数据长度
 * 返回 实际读取的数据长度
 */
int app_buffer_read(app_buffer_t *buffer, char *read_buff, int read_buff_len)
{
    /* 1 获取读锁 */
    pthread_mutex_lock(&buffer->read_lock);
    /* 根据下标u取出 读缓冲区 */
    app_buffer_sub_t *read_sub_buffer = buffer->sub_buffers[buffer->read_index];
    /* 判断 读缓冲区是否为空 */
    if (read_sub_buffer->data_len == 0)
    {
        /* 如果数据为空 */
        app_buffer_swap(buffer);
        read_sub_buffer = buffer->sub_buffers[buffer->read_index];
        /* 判断 读缓冲区是否为空 */
        if (read_sub_buffer->data_len == 0)
        {
            return -1;
        }
    }
    /* 4 如果有数据 取出 帧头数据长度 */
    int read_data_len = read_sub_buffer->data_ptr[0];
    /* 5 如果帧头数据长度 大于 读缓冲区数据长度 */
    if (read_data_len > read_buff_len)
    {
        log_error("帧头数据长度大于 读缓冲区数据长度");
        return -1;
    }
    /* 5.1 把数据读取到 read_buff中 */
    memcpy(read_buff, read_sub_buffer->data_ptr + 1, read_data_len);
    /* 5.2 删除已读取的数据 */
    memmove(read_sub_buffer->data_ptr, read_sub_buffer->data_ptr + read_data_len + 1, read_sub_buffer->data_len - read_data_len - 1);
    read_sub_buffer->data_len -= read_data_len + 1;
    /* 如果数据读取完毕后 发现长度为0 进行读写切换 */
    pthread_mutex_unlock(&buffer->read_lock);
    /* 返回 实际读取的数据长度 */
    return read_data_len;
}


void app_buffer_destroy(app_buffer_t *buffer)
{
    for (size_t i = 0; i < 2; i++)
    {
        free(buffer->sub_buffers[i]->data_ptr); /* 释放子缓冲区数据 */
        free(buffer->sub_buffers[i]); /* 释放子缓冲区结构体 */
    }
    pyhread_mutex_destroy(&buffer->read_lock);
    pyhread_mutex_destroy(&buffer->swap_lock);
    free(buffer);  /* 释放主缓冲区结构体 */
}